package com.gylang.springmini.factory;

import com.gylang.springmini.exception.BeansException;
import com.gylang.springmini.exception.NoSuchBeanDefinitionException;

import java.util.Optional;
import java.util.function.Supplier;

/**
 * @author gylang
 * data 2021/11/12
 */
public interface BeanFactory {

    /**
     * 获取指定的bean
     *
     * @param name bean的名称
     * @return bean的一个实例
     * @throws BeansException 如果bean不存在
     */
    Object getBean(String name) throws BeansException;

    /**
     * 获取指定的bean
     *
     * @param name         bean的名称
     * @param requiredType bean的类型
     * @param <T>          bean的类型
     * @return bean的一个实例
     * @throws BeansException 如果bean不存在
     */
    <T> T getBean(String name, Class<T> requiredType) throws BeansException;

    /**
     * 获取指定的bean
     *
     * @param name bean的名称
     * @param args 显性传递工厂参数/构造参数
     * @return bean的一个实例
     * @throws BeansException 如果bean不存在
     */
    Object getBean(String name, Object... args) throws BeansException;

    /**
     * 获取指定的bean
     *
     * @param requiredType bean的类型
     * @return bean的一个实例
     * @throws BeansException 如果bean不存在
     */
    <T> T getBean(Class<T> requiredType) throws BeansException;

    /**
     * 获取指定的bean
     *
     * @param requiredType bean的类型
     * @param args         显性传递工厂参数/构造参数
     * @return bean的一个实例
     * @throws BeansException 如果bean不存在
     */
    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
    /**
     * 获取指定的bean
     *
     * @param requiredType bean的类型
     * @param args         显性传递工厂参数/构造参数
     * @param allowEagerInit 是否允许早期对象
     * @return bean的一个实例
     * @throws BeansException 如果bean不存在
     */
    <T> T getBean(Class<T> requiredType, Boolean allowEagerInit, Object... args) throws BeansException;

    /**
     * 获取指定的bean
     *
     * @param requiredType bean的类型
     * @param allowEagerInit 是否允许获取未完成初始化的对象
     * @return bean的一个实例
     * @return 是否允许
     * @throws BeansException 如果bean不存在
     */
    <T> Supplier<T> getBeanSupplier(Class<T> requiredType, boolean allowEagerInit);

    /**
     * 获取指定的bean
     *
     * @param requiredType bean的类型
     * @return bean的包装类, 允许获取的bean为空
     * @throws BeansException 如果bean不存在
     */
    <T> Optional<T> getBeanOptional(Class<T> requiredType);

    /**
     * 获取指定的bean
     *
     * @param requiredType bean的类型
     * @param args         显性传递工厂参数/构造参数
     * @return bean的包装类, 允许获取的bean为空
     * @throws BeansException 如果bean不存在
     */
    <T> Optional<T> getBeanOptional(Class<T> requiredType, Object... args);

    /**
     * 判断是否存在该bean实例
     *
     * @param name bean的名称
     * @return 是否存在具有给定名称的 bean
     */
    boolean containsBean(String name);

    /**
     * 判断是否存在改bean的声明
     * @param beanName bean的名称
     * @return 是否存在改bean的声明
     */
    boolean containsBeanDefinition(String beanName);

    /**
     * 判断是否为单例
     * @param name bean的名称
     * @return 是否为单例
     * @throws NoSuchBeanDefinitionException 如果bean的声明不存在不存, 抛出异常
     */
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

    /**
     * 判断是否为原型模式 (多例)
     * @param name bean的名称
     * @return 是否为原型模式
     * @throws NoSuchBeanDefinitionException 如果bean的声明不存在不存, 抛出异常
     */
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;


}
